<template>
    <div class="M-form" v-if="inited">
        <!-- 需要解决的问题： 1、格式校验 -->
        <!-- 2、form 组件之间的 一个相互影响显示的问题  -->
        <!-- <div class="M-formTitle">我是一个自定义表单组件 </div> -->
        <div class="M-formItems" v-if="config && config.length">
            <div
                class="M-formItem"
                v-for="item in config"
                :key="item.key"
                v-show="showMap[item.key]"
            >
                <div class="label">
                    <i :class="{ v: item.required }">*</i>{{ item.title }}
                </div>
                <div class="ctrl">
                    <!-- 各种输入框 -->
                    <input
                        :type="item.type"
                        v-if="item.mod == 'input'"
                        v-model="result[item.key]"
                    />
                    <!-- 各种 select 框 -->
                    <select
                        v-if="item.mod == 'select'"
                        v-mode1="result[item.key]"
                    >
                        <option
                            v-for="option in item.options"
                            :key="option.val"
                            :value="option.val"
                        >
                            {{ option.name }}
                        </option>
                    </select>

                    <!-- 各种 radio -->
                    <div class="cell" v-if="item.mod == 'radio'">
                        <div
                            class="M-item"
                            v-for="option in item.options"
                            :key="option.val"
                        >
                            <input
                                type="radio"
                                :name="item.key"
                                :value="option.val"
                                v-model="result[item.key]"
                            />{{ option.name }}
                        </div>
                    </div>

                    <!-- 各种 checkbox -->
                    <div class="cell" v-if="item.mod == 'checkbox'">
                        <label
                            class="M-item"
                            v-for="option in item.options"
                            :key="option.val"
                        >
                            <input
                                type="checkbox"
                                :name="item.key"
                                :value="option.val"
                                v-model="result[item.key]"
                            />{{ option.name }}
                        </label>
                    </div>

                    <!-- 文件上传 -->
                    <!-- <div class="cell" v-if="item.mod == 'upload'"> -->
                    <!-- 可能会用到其它关联数据 -->
                    <!-- <upload :config="item.config" v-model:data="result[item.key]"></upload> -->
                    <!-- </div> -->

                    <!-- 可自行定义 -->
                    <div class="cell" v-if="item.mod == 'custom'">
                        <!-- 可能会用到其它关联数据 -->
                        <slot :name="item.key" v-bind="result"></slot>
                    </div>
                </div>
            </div>
        </div>

        <toast :show.sync="showToast" :text="toastTip"></toast>
    </div>
</template>
<script>
// import upload from "../../components/upload/index.vue";
import toast from "@/components/toast";
// 组件配置应该包含 key: input、select、radio 内置，其余复杂的 上传文件、picker 可以外置
export default {
    props: {
        config: {
            type: Array,
            default: function () {
                return [];
            },
        },
        data: Object,
    },
    computed: {
        // 展示状态，某些情况下，一个表单操作会影响另一个表单操作的显示和隐藏
        showMap: function () {
            let status = {};
            this.config.forEach((ele) => {
                status[ele.key] = ele.show ? ele.show(this.result, ele) : true;
            });
            return status;
        }
    },
    data: function () {
        return {
            result: {},
            inited: false,
            showToast: false,
            toastTip: ""
        };
    },
    created() {
        this.updating = false;
        // result 无法监听，也没有必要监听
        this.getResult();
        // 这之后剧联动上了
        this.$emit("update:data", this.result);
        window.setTimeout(() => {
            this.inited = true;
            this.$watch(
                "result",
                function (nval, oval) {
                    console.log("result 监听触发");
                },
                {
                    deep: true,
                }
            );
        });
        console.log('component form created');
    },
    methods: {
        tip(t) {
            this.toastTip = t;
            this.showToast = true;
        },
        // 对外暴露格式校验 接口
        validate: function () {
            return new Promise((resolve, reject) => {
                for (let item of this.config) {
                    // 必填才需要校验，必填的话需要提供了 validate 函数
                    if (
                        item.required &&
                        item.validate &&
                        this.showMap[item.key]
                    ) {
                        let res = item.validate(
                            this.result[item.key],
                            this.result,
                            item
                        );
                        if (res === true) continue;
                        else {
                            // 校验停止，且抛出校验结果
                            this.tip(res);
                            reject(item);
                            return;
                        }
                    }
                }
                // 校验通过
                resolve();
            });
        },
        getResult() {
            this.config &&
                this.config.length &&
                this.config.forEach((ele) => {
                    this.$set(this.result, ele.key, ele.value || "");
                });
        }
    },
    components: {
        toast,
    },
    beforeCreate(){
        console.log('component form beforeCreate');
    },
    mounted(){
        console.log('component form mounted');
    },
    beforeMount(){
          console.log('component form beforeMount');
    }
};
</script>
<style lang="less">
@th: 80px;
.M-form {
    background: #efefef;
    border-radius: 10px;
    &Title {
        text-align: center;
        line-height: @th;
        font-weight: bold;
        border-bottom: 1px solid #c1c1c1;
    }
    &Item {
        // margin-bottom: 10px;
        display: flex;
        border-bottom: 1px dashed #c1c1c1;
        .label,
        .ctrl {
            line-height: 40px;
        }
        .label {
            width: 160px;
            padding-left: 10px;
            font-size: 28px;
            height: @th;
            line-height: @th;
            display: flex;
            align-items: center;
            i {
                opacity: 0;
                color: red;
                padding: 0 5px;
                &.v {
                    opacity: 1;
                }
            }
        }
        .ctrl {
            flex: 1;
            input[type="text"],
            input[type="number"] {
                background: transparent;
                padding: 0;
                border: none;
                margin: 0;
                width: 100%;
                line-height: @th;
                :focus {
                    outline: none;
                }
            }
            .cell {
                display: flex;
                align-items: center;
                height: 100%;
                .M-item {
                    padding-right: 15px;
                    display: flex;
                    align-items: center;
                    input[type="checkbox"],
                    input[type="radio"] {
                        margin-right: 5px;
                    }
                }
            }
        }
    }
}
</style>